<?php
/**
 * Created by PhpStorm.
 * User: shaowei
 * Date: 2022/8/31
 * Time: 14:18
 */

namespace App\Datas;

use App\Tools\FunTool;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
use App\Datas\User;
use App\Tools\OssImgValidate;

class Opus
{
    protected $mark = '!down';

    public function __construct(){
        $platform = array_key_exists("HTTP_PLATFORM",$_SERVER) ? $_SERVER['HTTP_PLATFORM'] : 2;
        if ($platform == 1) {
            $this->mark = "!apple_down";
        } else {
            if (isset($_SERVER['HTTP_AI_LAN']) && $_SERVER['HTTP_AI_LAN'] == "zh") {
                $this->mark = "!android_zh_down";
            } else {
                $this->mark = "!android_en_down";
            }
        }
    }

    // 添加任务队列
    public function addPrint($prompt, $translatorPrompt, $taskId, $userId, $image = '', $type = 1, $negativePrompt = '', $translatorNegativePrompt = '', $height = 768, $width = 512, $dot = 0, $drawingId = 0, $drawingImage = "",$styleId = 0, $isHigh = 0,$isStyleOrginal = 0, $iPlatform = 0) {
        $prompt = false !== strpos($translatorPrompt, '***') ? $translatorPrompt : $prompt;
		$translatorPrompt = str_replace('***', '', $translatorPrompt);
		$prompt = str_replace('***', '', $prompt);
		
        $data = [
            'task_id' => $taskId,
            'guidance_scale' => 7.5,
            'num_inference_steps' => 50,
            'height' => $height,
            'width' => $width,
            'prompt' => $prompt,
            'translator_prompt' => $translatorPrompt,
            'image' => $image,
            'user_id' => intval($userId),
            'type' => $type,
            'negative_prompt' => $negativePrompt,
            'translator_negative_prompt' => $translatorNegativePrompt,
            'dot' => $dot,
            'drawing_id' => intval($drawingId),
            'style_id'=> intval($styleId),
            'isHigh'=> intval($isHigh),
            'is_style_orginal'=> $isStyleOrginal,
            'platform'=> $iPlatform,
        ];
        if ($drawingImage != "") {
            $imageInfo = getimagesize($drawingImage);
            $base64Img = 'data:' . $imageInfo['mime'] . ';base64,' . chunk_split(base64_encode(file_get_contents($drawingImage)));
            $data = array_merge($data, ['drawing_image' => [$base64Img], 'drawing_url' => $drawingImage]);
        }
        $key = 'painter:queue1';
        //Redis::rpush($key, json_encode($data));
        Log::info("addPrint", $data);
        $isDelay = $this->checkOpusDelayByUserId($userId);
        if ($isDelay) {
            $this->setTaskDelay($key,$data);
        } else {
            Redis::rpush($key, json_encode($data));
        }

        $queueSize = Redis::llen($key);
        $key = 'painter:task:' . $taskId;
        $retData = [
            'status' => 0,
            'url' => '',
            'size' => $queueSize,
            'index' => $queueSize,
            'time' => 8,
            'task_id' => $taskId,
            'refresh_uri' => '/v2/opus/task?task_id=' . $taskId,
            'refresh_time' => 3,
            'prompt' => $prompt,
            'type' => $type,
            'negative_prompt' => $negativePrompt,
            'translator_negative_prompt' => $translatorNegativePrompt,
            'height' => $height,
            'width' => $width,
            'image' => $image,
            'drawing_id' => intval($drawingId),
            'is_high' => $isHigh
        ];
        if ($drawingImage != "") {
            $retData = array_merge($retData, ['drawing_image' => $drawingImage]);
        }
        $this->setUserTask($userId, $taskId);
        Redis::hmset($key, $retData);
        Redis::EXPIRE($key, 3600*24);

        // 设置用户处理的数量
        $lenKey = 'painter:user:len:'. $userId;
        Redis::INCRBY($lenKey, 1);
        Redis::EXPIRE($lenKey, 600);
        return $retData;
    }

    /**
     * @param $modelId 模型ID
     * @param $model 模型
     * @param $machineId 机器ID
     * @param $taskId 任务ID
     * @param $userId 用户ID
     * @param $type 类型，1文生图，2图生图
     * @param $prompt 描述词
     * @param $translatorPrompt 翻译后的描述测
     * @param $negativePrompt 反向描述词
     * @param $height 高
     * @param $width 宽
     * @param $drawingImage 图生图的原图
     * @param $isHigh 是否高清
     * @param int $styleId 词条ID
     * @param int $isStyleOrginal 是否使用原始词条，即用户没有修改描述词
     * @param int $iPlatform 1:ios 2:安卓
     * @return array
     */
    public function addNewPrint($modelId,$model, $machineId, $taskId, $userId, $type = 1, $prompt, $translatorPrompt, $negativePrompt = '', $height = 768, $width = 512, $drawingImage = "",$isHigh = 0,$styleId = 0, $isStyleOrginal = 0, $iPlatform = 0, $special = 0) {
        //$prompt = false !== strpos($translatorPrompt, '***') ? $translatorPrompt : $prompt;
		$translatorPrompt = str_replace('***', '', $translatorPrompt);
		//$prompt = str_replace('***', '', $prompt);

		$iUserID = intval($userId);
		$iIsTry = empty($iUserID) ? 1 : 2;
		if(1 == $iIsTry && in_array($type, [1, 2])) {//(bikini:0.9)
			//$translatorPrompt = '(sfw:0.9)'.$translatorPrompt;
            //$translatorPrompt = '<lora:ClothingAdjuster3:-1.0>'.$translatorPrompt;
		}
        if ($iPlatform == 1 && in_array($type, [1, 2])) {
            $translatorPrompt = '<lora:ClothingAdjuster3:-1.0>'.$translatorPrompt;
        }

		//$type [1 文生图; 2 二次元作画; 3 图生图]
        $data = [
            'task_id' => $taskId,
            'prompt' => $prompt,
            'translator_prompt' => $translatorPrompt,
            'negative_prompt' => $negativePrompt,
            'height' => $height,
            'width' => $width,
            'device_id' => FunTool::getDeviceId(),
            'user_id' => $iUserID,
            'type' => $type,
            'model_id' => intval($modelId),
            'model' => $model,
            'drawing_url' => $drawingImage,
            'isHigh' => intval($isHigh),
            'dot' => $isHigh == 1 ? FunTool::getHighDrawingDot() : 0,
            'style_id' => intval($styleId),
            'is_style_orginal' => $isStyleOrginal,
            'platform' => $iPlatform,
            'is_try' => $iIsTry
        ];
        if ($special == 1) {
            $data['dot'] = 0;
        }
        // Log::info("addNewPrint", $data);
        /*if ($drawingImage != "") {
            $imageInfo = getimagesize($drawingImage);
            $base64Img = 'data:' . $imageInfo['mime'] . ';base64,' . chunk_split(base64_encode(file_get_contents($drawingImage)));
            $data = array_merge($data, ['drawing_image' => [$base64Img], 'drawing_url' => $drawingImage]);
        }*/
        $key = "painter:{$machineId}:queue";

        $isDelay = $this->checkOpusDelayByUserId($userId);//是否要进入延时队列
        if ($isDelay) {
            $this->setTaskDelay($key,$data);
        } else {
            Redis::rpush($key, json_encode($data));
        }

        $queueSize = Redis::llen($key);
        $key = 'painter:task:' . $taskId;
        $retData = [
            'status' => 0,
            'url' => '',
            'size' => $queueSize,
            'index' => $queueSize,
            'time' => 8,
            'task_id' => $taskId,
            'refresh_uri' => '/v2/opus/task?task_id=' . $taskId,
            'refresh_time' => 3,
            'prompt' => $prompt,
            'type' => $type,
            'negative_prompt' => $negativePrompt,
            'height' => $height,
            'width' => $width,
            'model_id' => intval($modelId),
            'is_high' => $isHigh
        ];
        if ($drawingImage != "") {
            $retData = array_merge($retData, ['drawing_image' => $drawingImage]);
        }
        $this->setUserTask($userId, $taskId);
        Redis::hmset($key, $retData);
        Redis::EXPIRE($key, 3600*24);

        // 设置用户处理的数量
        $this->setUserLen($userId);
        return $retData;
    }

    /**
     * @param $userId
     * @return void
     */
    public function setUserLen($userId) {
        $userId = $userId < 1 ? FunTool::getDeviceId() : $userId;
        $lenKey = 'painter:user:len:'. $userId;
        Redis::INCRBY($lenKey, 1);
        Redis::EXPIRE($lenKey, 600);
    }

    /**
     * 获取长度
     * @param $userId
     * @return int
     */
    public function getUserLen($userId) {
        $userId = $userId < 1 ? FunTool::getDeviceId() : $userId;
        $lenKey = 'painter:user:len:'. $userId;
        $len = Redis::GET($lenKey);
        if (!$len) {
            return 0;
        }
        return intval($len);
    }

    public function getFreeNum($deviceId)
    {
        return DB::table('opus')->where(['device_id' => $deviceId])->count();
    }

    public function getCountByWhere($where) {
        return DB::table('opus')->where($where)->where('created_at','like',date('Y-m-d').'%')->count();
    }

    public function addPrintNoVip($prompt, $taskId, $userId, $deviceId = "",$promptKey = 0,$bIsTry=false) {
        $demoData = DB::table('opus')->where(['prompt'=>$prompt,"device_id" => $deviceId])->inRandomOrder()->first();
        //$url = 'https://overseas-files.dalleai.art/changsha/01.webp';
        $urls = FunTool::getRandomUrlByPropmt($promptKey);
        //兜底
        $url = $urls[0];
        if ($demoData) {
            $url = $urls[1];
        }

        $retData = [
            'status' => 0,
            'url' => '',
            'size' => 1,
            'index' => 1,
            'time' => 8,
            'task_id' => $taskId,
            'refresh_uri' => '/v2/opus/task?task_id=' . $taskId,
            'refresh_time' => 3,
            'prompt' => $prompt,
            'type' => 1,
            'negative_prompt' => '',
            'height' => 768,
            'width' => 512,
            'image' => '',
            'device_id' => $deviceId
        ];
        $saveData = $retData;
        $saveData['url'] = $url;
        $saveData['status'] = 2;
        $key = 'painter:task:' . $taskId;
        // $this->setDeviceTask($deviceId, $taskId);
        Redis::hmset($key, $saveData);
        Redis::EXPIRE($key, 3600*24);

        DB::table('opus')->insert([
            'user_id' => $userId,
            'prompt' => $prompt,
            'task_id' => $taskId,
            'url' => $url,
            'title' => $prompt,
            'height' => 768,
            'review_status' => 1,
            'device_id' => $deviceId,
            'is_try' => ($bIsTry?1:2)
        ]);

        return $retData;
    }

    public function freePut($userId, $deviceId)
    {
        if (!$deviceId) {
            return false;
        }

        DB::table('opus')->where(['device_id' => $deviceId, 'user_id' => 0])->update(['user_id' => $userId]);
    }

    public function getDemo($prompt) {

    }

    public function incCount($userId) {
        $key = 'painter:novip:' . $userId;
        $count = Redis::INCR($key);
        Redis::EXPIRE($key, 3600*24*3);
        return $count;
    }

    public function getCount($userId) {
        $key = 'painter:novip:' . $userId;
        $ret = Redis::GET($key);
        if (!$ret) {
            return 0;
        }
        return intval($ret);
    }

    public function setUserTask($userId, $taskId) {
        $userId = $userId < 1 ? FunTool::getDeviceId() : $userId;
        $key = 'painter:task:user' . $userId;
        Redis::hset($key, $taskId, time());
        Redis::EXPIRE($key, 3600*12);
    }

    public function getUserTask($userId) {
        $userId = $userId < 1 ? FunTool::getDeviceId() : $userId;
        $key = 'painter:task:user' . $userId;
        $data = Redis::HKEYS($key);
        if (!$data) {
            return [];
        }
        return $data;

    }

    public function getUserNewTask($userId, $deviceId){
        $now = date('Y-m-d H:i:s');
        if ($userId > 0) {
            $tasks = DB::table('task_img')->where('user_id', $userId)->where('status',0)->where('expire_time','>=', $now)->select('task_id')->get()->toArray();
        }else{
            $tasks = DB::table('task_img')->where('device_id', $deviceId)->where('status',0)->where('expire_time','>=', $now)->select('task_id')->get()->toArray();
        }
        if (!empty($tasks)) {
            return array_column($tasks, 'task_id');
        }else{
            return [];
        }
    }

    public function getTaskBack($taskId) {
        $key = 'painter:task:' . $taskId;
        $retData = Redis::HGETALL($key);
        if (!$retData) {
            return null;
        }
        //过了10分钟，就不显示了
        $expir = Redis::TTL($key);
        //Log::info("getTask",["task_id" => $taskId,"expir" => $expir,"check" => ($expir < 85800)]);
        if ($expir < 85800) {
            return "";
        }
        $retData['size'] = intval($retData['size']);
        $retData['index'] = intval($retData['index']);
        $retData['refresh_time'] = intval($retData['refresh_time']);
        $retData['status'] = intval($retData['status']);
        $retData['time'] = intval($retData['time']);
        $retData['down_url'] = $retData['url'] . $this->mark;

        // $retData['down_url'] = $retData['url'];
        $retData['fmt_prompt'] = isset($retData['translator_negative_prompt']) ? $retData['translator_negative_prompt'] : '';

		//图片审核
		$aTask = (array)DB::table('opus')->where(['task_id' => $taskId])->first();
		if(!empty($aTask) && !empty($aTask['device_id'])) {
			$aDevice = (array)DB::table('system_device')->where(['device_id' => $aTask['device_id']])->first();
			//Log::info("getTaskTest.", ["taskId" => $taskId, "aTask" => $aTask, "aDevice" => $aDevice]);
			//if(!empty($aDevice['user_id']) && 'ios' == $aDevice['platform']) {
			if('ios' == $aDevice['platform']) {
				$oOssImgValidate = new OssImgValidate();
				$ResValidate = $oOssImgValidate->validate($retData['down_url']);
				if(false == $ResValidate) {
					$retData['down_url'] = $oOssImgValidate->sDefaultImgUrl;
					$retData['url'] = $oOssImgValidate->sDefaultImgUrl;

					$_aUpdate['is_verify'] = 2;
					$_aUpdate = ['is_verifyed' => 1];
					$_aUpdate['url'] = $oOssImgValidate->sDefaultImgUrl;
					DB::table('opus')->where(['task_id' => $taskId])->update($_aUpdate);

					Log::info("getTask.", ["taskId" => $taskId, "retData" => $retData]);
				}
			}
		}

        return $retData;
    }

    public function getTask($taskId) {
        $now = date('Y-m-d H:i:s');
        $task_info = DB::table('task_img')->where('task_id',$taskId)->where('expire_time','>=', $now)->first();
        if (empty($task_info)) {
            return [];
        }
        $extend = $task_info->extend;
        if (empty($extend)) {
            return [];
        }
        $extend = json_decode($extend, true);
        $retData = $extend['task_loading'];
        $retData['size'] = intval($retData['size']);
        $retData['index'] = intval($retData['index']);
        $retData['refresh_time'] = intval($retData['refresh_time']);
        $retData['status'] = intval($retData['status']);
        $retData['time'] = intval($retData['time']);
        $retData['down_url'] = $extend['success_img_url'] ?? '';
        $retData['down_video_url'] = $extend['success_video_url'] ?? '';
        $retData['fmt_prompt'] = isset($retData['translator_negative_prompt']) ? $retData['translator_negative_prompt'] : '';
        $retData['type'] = $task_info->type;
        return $retData;
    }

    /**
     * 获取所有风列表
     */
    public function getStyles($lanage = 'zh') {
        $data = DB::table('opus_style')->where(['lanage'=>$lanage])->get();
        return $data->toArray();
    }


    /**
     * 获取一个风格
     */
    public function getStyle($styleId) {
        $data = DB::table('opus_style')->where(['id'=>$styleId])->first();
        if (!$data) {
            return null;
        }

        return (array) $data;
    }


    /**
     * 获取推荐信息
     */
	public function getTop($index, $len, $lanage, $sOrderBy = 'id', $sSort = 'desc') {
		//
		if('desc' == $sSort) {
			$data = DB::table('opus')->leftJoin('user', 'opus.user_id', '=', 'user.id')->where([
				'opus.top' => 1, 'opus.delete' => 0, 'opus.lanage' => $lanage
			])
				//->where('user.nickname', '<>', '')
					  ->limit($len)
					  ->offset($index)
					  ->orderByDesc('opus.created_at')
					  ->get([
							  'user.nickname', 'opus.user_id', 'opus.prompt', 'opus.negative_prompt', 'opus.img', 'opus.type',
							  'opus.width', 'opus.height', 'opus.title', 'opus.id', 'opus.dot',
							  DB::raw("CONCAT(url,'!webp') AS url"), DB::raw("CONCAT(url,'".$this->mark."') AS down_url"),
							  'opus.contri_status', DB::raw("CONCAT(url,'!thumbnail') AS thumb_url")
						  ]
					  );
		}else{
			$data = DB::table('opus')->leftJoin('user', 'opus.user_id', '=', 'user.id')->where([
				'opus.top' => 1, 'opus.delete' => 0, 'opus.lanage' => $lanage
			])
				//->where('user.nickname', '<>', '')
					  ->limit($len)
					  ->offset($index)
					  ->oldest('opus.created_at')
					  ->get([
							  'user.nickname', 'opus.user_id', 'opus.prompt', 'opus.negative_prompt', 'opus.img', 'opus.type',
							  'opus.width', 'opus.height', 'opus.title', 'opus.id', 'opus.dot',
							  DB::raw("CONCAT(url,'!webp') AS url"), DB::raw("CONCAT(url,'".$this->mark."') AS down_url"),
							  'opus.contri_status', DB::raw("CONCAT(url,'!thumbnail') AS thumb_url")
						  ]
					  );
		}
		return $data->toArray();

    }


    /**
     * 获取样例数据
     */
    public function getExample($index, $len, $lanage = 'en') {
        $data = DB::table('opus')->leftJoin('user', 'opus.user_id', '=', 'user.id')
            ->where([
                'opus.example' => 1,
                'opus.delete' => 0,
                'opus.lanage' => $lanage
            ])
            ->limit($len)
            ->offset($index)
            ->orderByDesc('opus.created_at')
            ->get(
                ['user.nickname','opus.user_id','opus.prompt','opus.negative_prompt','opus.img','opus.width','opus.height','opus.title', 'opus.id', 'opus.dot',DB::raw("CONCAT(url,'!webp') AS url"),DB::raw("CONCAT(url,'" . $this->mark . "') AS down_url"),DB::raw("CONCAT(url,'!thumbnail') AS thumb_url")]
            );
        return $data->toArray();
    }


    /**
     * 获取最新数据
     */
    public function getNew($index, $len, $lanage = 'en') {
        $data = DB::table('opus')->leftJoin('user', 'opus.user_id', '=', 'user.id')

            ->where([
                'opus.delete' => 0,
                'opus.new' => 1,
                'opus.lanage' => $lanage
            ])
            ->limit($len)
            ->offset($index)
            ->orderByDesc('opus.created_at')
            ->get(
                ['user.nickname','opus.user_id','opus.prompt','opus.img','opus.negative_prompt','opus.type','opus.width','opus.height','opus.title', 'opus.id', 'opus.dot',DB::raw("CONCAT(url,'!webp') AS url"),DB::raw("CONCAT(url,'" . $this->mark . "') AS down_url"), 'opus.contri_status',DB::raw("CONCAT(url,'!thumbnail') AS thumb_url")]
            );
        return $data->toArray();
    }


    /**
     * 更新标题
     */
    public function setTitle($taskId, $title, $userId) {
        return DB::table('opus')->where(['task_id'=>$taskId, 'user_id'=>$userId])->update(['title'=>$title]);
    }


    public function setTitlex($id, $title, $userId) {
        return DB::table('opus')->where(['id'=>$id, 'user_id'=>$userId])->update(['title'=>$title]);
    }


    /**
     * 删除数据
     */
    public function del($id, $userId) {
        return DB::table('opus')->where(['id'=>$id,'user_id'=>$userId])->update(['delete'=>1]);
    }


    /**
     * 删除数据width taskId
     */
    public function delWithTaskId($taskId, $userId) {
        return DB::table('opus')->where(['task_id'=>$taskId, 'user_id'=>$userId])->update(['delete'=>1]);
    }

    /**
     * 获取用户数据
     */
    public function getUser($userId,$deviceId, $index, $len) {
        $where = ["opus.delete" => 0,"opus.user_id" => 0];
        if ($userId > 0) {
            $where["opus.user_id"] = $userId;
        }else {
            $where["opus.device_id"] = $deviceId;
        }
        //Log::info("getUser",["user_id" => $userId,"device_id" => $deviceId,"index" => $index,"len" => $len]);
        $data = DB::table('opus')->leftJoin('user', 'opus.user_id', '=', 'user.id')
            ->where($where)
            ->limit($len)
            ->offset($index)
            ->orderByDesc('opus.created_at')
            ->get([
					'user.nickname', 'opus.user_id', 'opus.prompt', 'opus.type', 'opus.width', 'opus.height',
					'opus.title', 'opus.id', 'opus.dot','opus.is_verify', 'opus.is_verifyed','opus.is_high','opus.video_url',
					DB::raw("CASE WHEN review_status='1' THEN CONCAT(url,'') WHEN use_dot>0 and review_status !='1' THEN 'https://overseas-files.dalleai.art/default-dot.png' ELSE 'https://overseas-files.dalleai.art/default.png' END AS 'down_url'"),
					DB::raw("CASE WHEN review_status='1' THEN CONCAT(url,'!webp') WHEN use_dot>0 and review_status !='1' THEN 'https://overseas-files.dalleai.art/default-dot.png' ELSE 'https://overseas-files.dalleai.art/default.png' END AS 'url'"),
					'opus.review_status', 'opus.contri_status',
					DB::raw("CASE WHEN review_status='1' THEN CONCAT(url,'!thumbnail') WHEN use_dot>0 and review_status !='1' THEN 'https://overseas-files.dalleai.art/default-dot.png' ELSE 'https://overseas-files.dalleai.art/default.png' END AS 'thumb_url'"),

				]);
        $retData = $data->toArray();


		//$iPlatform = array_key_exists("HTTP_PLATFORM", $_SERVER) ? $_SERVER['HTTP_PLATFORM'] : 2;//1: ios   2: 安卓
		//图片审核
		//if(1 == $iPlatform) {// ios
		//	$oOssImgValidate = new OssImgValidate();
		//	foreach($retData as &$_aData) {
		//		if(1 == $_aData['is_verifyed']) {
		//			continue;
		//		}
		//		$ResValidate = $oOssImgValidate->validate($_aData['down_url']);
		//		$_aUpdate = ['is_verifyed' => 1];
		//		if(false == $ResValidate) {
		//			$_aUpdate['is_verify'] = 2;
		//			$_aUpdate['url'] = $oOssImgValidate->sDefaultImgUrl;
		//
		//			$_aData['down_url'] = $oOssImgValidate->sDefaultImgUrl;
		//			$_aData['url'] = $oOssImgValidate->sDefaultImgUrl;
		//			$_aData['thumb_url'] = $oOssImgValidate->sDefaultImgUrl;
		//		}
		//		DB::table('opus')->where(['id'=>$_aData['id']])->update($_aUpdate);
		//	}
		//}

        if ($index > 0) {
            return $retData;
        }
        //Log::info("getUser",["check" => ($index > 0)]);
        //$userTask = $this->getUserTask($userId);
        $userTask = $this->getUserNewTask($userId, $deviceId);
        //Log::info("getUser",["user_task" => $userTask]);
        $dbUserTask = DB::table('opus')
            ->where([
            'user_id' => $userId
        ])
            ->whereIn('task_id', $userTask)
            ->get(['task_id']);
        $dbUserTask = $dbUserTask->toArray();
        $dbUserTask = array_column($dbUserTask, 'task_id');
        foreach ($userTask as $taskId) {
            if(!in_array($taskId, $dbUserTask)) {
                $taskData = $this->getTask($taskId);
                if (!$taskData) {
                    continue;
                }
                //Log::info("getUser",["task_id" => $taskId,"task_data" => $taskData]);
                //print_r($taskData);
                if ($taskData["status"] == 2) {
                    continue;
                }
                $tmpTaskData = [
                    'nickname' => '',
                    'user_id' => $userId,
                    'prompt' => $taskData['prompt'],
                    'url' => $taskData['url'],
                    'video_url' => $taskData['down_video_url'],
                    'size' => $taskData['size'],
                    'index' => $taskData['index'],
                    'time' => $taskData['time'],
                    'status' => $taskData['status'],
                    'refresh_time' => $taskData['refresh_time'],
                    'refresh_uri' => $taskData['refresh_uri'],
                    'type' => $taskData["type"]

                ];
                array_unshift($retData, $tmpTaskData);
            }
        }
        return $retData;
    }

    public function get($opusId) {
        $data = Db::table('opus')->where([
            'id' => $opusId,
        ])->first();

        if (!$data) {
            return null;
        }

        return (array) $data;
    }


    public function getRead($userId, $opusId) {
        $data = Db::table('opus_read')->where([
            'user_id' => $userId,
            'opus_id' => $opusId
        ])->first();

        if (!$data) {
            return null;
        }

        return (array) $data;
    }

    public function insertRead($userId, $opusId, $dot) {
        return DB::table('opus_read')->insert([
            'user_id' => $userId,
            'opus_id' => $opusId,
            'dot' => $dot
        ]);
    }


    /**
     * 监测是否超时
     * @param $userId
     */
    public function checkIntervalTime($userId) {
        $key = 'INTERVALTIME:'.$userId;
        $ret = Redis::SETNX($key, 1);
        if ($ret) {
            Redis::EXPIRE($key, 10);
        }
        return $ret;

    }


    public function getBuyList($userId, $index, $len) {
        $data = Db::table('opus_read')->leftJoin('opus', 'opus_read.opus_id', '=', 'opus.id')->leftJoin('user','user.id', '=', 'opus.user_id')->where([
            'opus_read.user_id' => $userId,
        ])->limit($len)
            ->offset($index)
            ->orderByDesc('opus_read.created_at')
            ->get(
                ['user.nickname','opus.prompt','opus.url','opus.type','opus.width','opus.height','opus.title', 'opus.id', 'opus.dot',DB::raw("CONCAT(url,'" . $this->mark . "') AS down_url"),DB::raw("CONCAT(url,'!thumbnail') AS thumb_url")]
            );
        return $data->toArray();
    }

    public function getCacheTranslator($prompt) {
        $hash = md5($prompt);
        $key = 'painter:opus:translator:'.$hash;
        return Redis::get($key);
    }


    public function search($keyWord, $len, $index) {
        $data = DB::table('opus')
            ->limit($len)
            ->offset($index)
            ->orderByDesc('created_at')
            ->where(['delete' => 0, 'review_status' => 1])
            ->get(
                ['opus.id','opus.prompt','opus.width','opus.negative_prompt','opus.img','opus.height','opus.title', 'opus.dot',DB::raw("CONCAT(url,'!webp') AS url"),DB::raw("CONCAT(url,'" . $this->mark . "') AS down_url"),DB::raw("CONCAT(url,'!thumbnail') AS thumb_url")]
            );
        return $data->toArray();
    }


    public function setCacheTranslator($prompt, $tprompt) {
        $hash = md5($prompt);
        $key = 'painter:opus:translator:'.$hash;
        return Redis::SETEX($key, 24*3600, $tprompt);
    }


    public function getAnimeExample($size, $lanage = 'zh') {
        $data = DB::select("select * from ap_opus_anime_example where lanage = '{$lanage}' order by RAND() limit 0,{$size}");
        return $data;
        //return array_map('get_object_vars', $data);
    }

    /**
     * 获取作品详情
     */
    public function getDetail($id)
    {
        $data = DB::table('opus')->leftJoin('user', 'opus.user_id', '=', 'user.id')
            ->where(['opus.delete' => 0, 'opus.id' => $id])
            ->select(['opus.*','user.*','opus.id as id','opus.dot as dot','opus.negative_prompt as fmt_prompt'])
            ->first();

        if (!$data) {
            return null;
        }

        $data = (array)$data;
        if ($data['review_status'] != 1 && $data['use_dot'] > 0) {
            $data['url'] = 'https://overseas-files.dalleai.art/default-dot.png';
        }
        if ($data['review_status'] != 1 && $data['use_dot'] == 0) {
            $data['url'] = 'https://overseas-files.dalleai.art/default.png';
        }
        $data['down_url'] = $data['url'] . $this->mark;
        // $data['down_url'] = $data['url'];
        return  $data;

    }

    /**
     * @desc 获取用户每日累计作画总数
     */
    public function getPaintCountOfDay($userId)
    {
        return true;
        $times = date('ymd');
        $key = 'painter:user:count:' . $times; //hash
        $uPaintCount = Redis::hget($key, $userId) ?? 0;
        if ($uPaintCount >= 100) {
            return false;
        }

        return true;
    }

    /**
     * @desc 增加用户每日累计作画总数
     */
    public function setPaintCountOfDay($userId)
    {
        $times = date('ymd');
        $key = 'painter:user:count:' . $times; //hash
        $uPaintCount = Redis::hincrby($key, $userId, 1);
        if(Redis::TTL($key) == -1){
            Redis::EXPIRE($key, 24 * 3600 * 2);
        }

        return true;
    }

    /**
     * 获取用户作品详情
     */
    public function getOpusDetail($userId, $id, $field = ['*'])
    {
        $data = DB::table('opus')
            ->select($field)
            ->where(['delete' => 0, 'review_status' => 1, 'id' => $id, 'user_id' => $userId])
            ->first();

        if (!$data) {
            return null;
        }

        return (array) $data;

    }

    /**
     * 更新作品数据
     */
    public function updateData($userId, $id, $data) {
        if (!$data) {
            return false;
        }
        return DB::table('opus')->where(['id'=>$id, 'user_id'=>$userId])->update($data);
    }

    /**
     * 获取用户社区置顶消息
     */
    public function getMessage($userId)
    {
        $key = "painter:user:contri:" . $userId;
        return Redis::get($key) ?? 0;
    }

    /**
     * 投稿通过
     */
    public function examineOpus($userId, $id, $opus, $type)
    {
        $point = config('app.contribution_num');
        $update = ['contri_status' => $type];

        if ($opus['contri_status'] == $type)  {
            return false;
        }

        if ($type == 3) {
            $key = "painter:user:contri:" . $userId;
            Redis::incrby($key, $point);    //增加200点数

            if(Redis::TTL($key) == -1){
                Redis::EXPIRE($key, 24 * 3600 * 10);
            }

            $userObj = new User();
            $userObj->updateDot($userId, $point, 7);

            $update = array_merge($update, ['new' => 1]);
        }

        $this->updateData($userId, $id, $update);

        return true;
    }

    /**
     * 用户
     */
    public function onclick($userId)
    {
        $key = "painter:user:contri:" . $userId;
        Redis::del($key);

        return true;
    }

    public function test()
    {
        $data = DB::table('opus')->where([
            'new' => 1,
        ])->get();
        $res = $data->toArray();
        $res = json_decode(json_encode($res), true);
        foreach ($res as $key => $value) {
            $rand = rand(1, 50);
            DB::table('opus')->where([
                'new' => 1,
                'id' => $value['id']
            ])->update(['user_id' => $rand]);
        }
    }

    /**
     * 将任务放到延时队列中
     * @param $taskQueueKey
     * @param $taskData
     * @return void
     */
    public function setTaskDelay($taskQueueKey,$taskData) {
        if (!array_key_exists("is_delay",$taskData)) {
            $taskData["is_delay"] = 1;
        }

        Redis::rpush("delay_task_queue", json_encode([
            "queue_key" => $taskQueueKey,
            "task" => $taskData,
        ]));
    }

    /**
     * 用户每天的作图数量
     * @param $userId
     * @return int
     */
    public function getDayCountByUserId($userId) {
        if ($userId < 1) {
            return 0;
        }
        return DB::table("opus")
            ->where(["user_id" => $userId])
            ->whereBetween("created_at",[date("Y-m-d 00:00:00"),date("Y-m-d 23:59:59")])
            ->count();
    }

    /**
     * 是否要进入延时队列
     * @param $userId
     * @return bool
     */
    public function checkOpusDelayByUserId($userId) {
        return false;
        $dayCount = $this->getDayCountByUserId($userId);
        if ($dayCount > env('USER_DAY_MAX_OPUS')) {
            return true;
        }
        return false;
    }


	/**
	 * @creater eks
	 */
	public function formatOpusWhere($aSearch) {
		$aWhere = [];
		if(!empty($aSearch) && is_array($aSearch)) {
			if(!empty($aSearch['id'])) {
				$aWhere['id'] = $aSearch['id'];
			}

			if(!empty($aSearch['user_id'])) {
				$aWhere['user_id'] = $aSearch['user_id'];
			}
			if(!empty($aSearch['delete'])) {
				$aWhere['delete'] = $aSearch['delete'];
			}
			if(!empty($aSearch['review_status'])) {
				$aWhere['review_status'] = $aSearch['review_status'];
			}
			if(!empty($aSearch['is_verify'])) {
				$aWhere['is_verify'] = $aSearch['is_verify'];
			}

			//
			if(!empty($aSearch['create_date'])) {
				$aSearch['create_egt'] = $aSearch['create_date'].' 00:00:00';
				$aSearch['create_elt'] = $aSearch['create_date'].' 23:59:59';
			}
			if(!empty($aSearch['create_egt']) && !empty($aSearch['create_elt'])) {
				$aWhere['created_at'] = array(
					'between', array(
						$aSearch['create_egt'], $aSearch['create_elt']
					)
				);
			} else {
				if(!empty($aSearch['create_egt'])) {//>=
					$aWhere['created_at'] = array(
						'egt', $aSearch['create_egt']
					);
				}
				if(!empty($aSearch['create_elt'])) {//<=
					$aWhere['created_at'] = array(
						'elt', $aSearch['create_elt']
					);
				}
			}
		}
		return $aWhere;
	}

	/**
	 * 用户生成图片列表
	 * @param array    $aWhere
	 * @param int $iPage
	 * @param int $iPageSize
	 * @return array
	 */
	public function getOpusList($aWhere, $iPage=1, $iPageSize=10) {
		$iOffset = (!empty($iPage) ? ($iPage - 1) : 0) * $iPageSize;
		$aWhere['delete'] = 0;
		$aWhere['review_status'] = 1;
		$aWhere = $this->formatOpusWhere($aWhere);

		$aDataList = DB::table('opus')
				  ->limit($iPageSize)
				  ->offset($iOffset)
				  ->orderByDesc('id')
				  ->where($aWhere)
				  ->get(
					  ['opus.id','opus.prompt','opus.width','opus.negative_prompt','opus.height','opus.title','opus.dot','opus.is_verify', 'opus.user_id','opus.created_at',DB::raw("CONCAT(url,'!webp') AS url"),DB::raw("CONCAT(url,'" . $this->mark . "') AS down_url"),DB::raw("CONCAT(url,'!thumbnail') AS thumb_url")]
				  );
		return $aDataList->toArray();
	}

	/**
	 * 用户生成图片数量
	 * @param array $aWhere
	 * @return int
	 */
	public function getOpusAmount($aWhere) {
		$aWhere['delete'] = 0;
		$aWhere['review_status'] = 1;
		$aWhere = $this->formatOpusWhere($aWhere);

		return DB::table('opus')->where($aWhere)->count();
	}

	public function getOpusByID($iID) {
		$data = Db::table('opus')->where([
			'id' => $iID
		])->first();

		if(!$data) {
			return null;
		}

		return (array)$data;
	}

	/**
	 * 更新据
	 * @param int   $iID
	 * @param array $aUpdate
	 * @return false|int
	 */
	public function updateOpusByID($iID, $aUpdate) {
		if(empty($iID) || empty($aUpdate)) {
			return 0;
		}
		$aWhere = ['id' => $iID];
		return DB::table('opus')->where($aWhere)->update($aUpdate);
	}

    public function getNoHighAmountByDay($userId, $deviceId){
        $amount = 0;
        $day = date('Y-m-d');
        if ($userId > 0) {
            $amount = DB::table('opus')->where('user_id',$userId)->where('is_high',0)->where('created_at','like',$day.'%')->count();
        }else{
            $amount = DB::table('opus')->where('device_id',$deviceId)->where('is_high',0)->where('created_at','like',$day.'%')->count();
        }
        return $amount;
    }

    public function getAmountByDay($userId, $deviceId){
        $amount = 0;
        $day = date('Y-m-d');
        if ($userId > 0) {
            $amount = DB::table('opus')->where('user_id',$userId)->where('created_at','like',$day.'%')->count();
        }else{
            $amount = DB::table('opus')->where('device_id',$deviceId)->where('created_at','like',$day.'%')->count();
        }
        return $amount;
    }

    public function getLastOpuInfo($userId, $deviceId){

        $info = [];
        $day = date('Y-m-d');
        if ($userId > 0) {
            $info = DB::table('opus')->where('user_id',$userId)->where('created_at','like',$day.'%')->select('is_high')->orderByDesc('id')->first();
        }else{
            $info = DB::table('opus')->where('device_id',$deviceId)->where('created_at','like',$day.'%')->select('is_high')->orderByDesc('id')->first();
        }
        return $info ? (array)$info : [];
    }


}